/*
 * Copyright (c) 2019, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2019-07-17     Wu Han       The first version
 */

#include "single_phase_encoder.h"

static rvm_dev_t *gpio_pin = NULL;

struct single_phase_encoder
{
    struct encoder  enc;
    rvm_dev_t *     pin;            /* interrupt pin  */
};

static void encoder_isr(rvm_dev_t *dev, void *arg)
{
    signed int* pulse_count = (signed int*)arg;
    (*pulse_count)++;
}

static signed long single_phase_encoder_enable(void *enc)
{
    single_phase_encoder_t enc_sub = (single_phase_encoder_t)enc;

    // Attach interrupts
    rvm_hal_gpio_pin_set_mode((rvm_dev_t *)(enc_sub->pin), RVM_GPIO_MODE_PULLNONE);

    rvm_hal_gpio_pin_set_direction((rvm_dev_t *)(enc_sub->pin), RVM_GPIO_DIRECTION_INPUT);

    rvm_hal_gpio_pin_set_direction((rvm_dev_t *)(enc_sub->pin), RVM_GPIO_DIRECTION_INPUT);

    rvm_hal_gpio_pin_attach_callback((rvm_dev_t *)(enc_sub->pin), encoder_isr, &(enc_sub->enc.pulse_count));

    rvm_hal_gpio_pin_set_irq_mode((rvm_dev_t *)(enc_sub->pin), RVM_GPIO_IRQ_MODE_RISING_EDGE);
    
    enc_sub->enc.last_time = aos_sys_tick_get();

    return  rvm_hal_gpio_pin_irq_enable((rvm_dev_t *)(enc_sub->pin), 1);
}

static signed long single_phase_encoder_disable(void *enc)
{
    single_phase_encoder_t enc_sub = (single_phase_encoder_t)enc;

    return rvm_hal_gpio_pin_irq_enable((rvm_dev_t *)(enc_sub->pin), 0);
}

static signed long single_phase_encoder_destroy(void *enc)
{
    single_phase_encoder_disable(enc);
    single_phase_encoder_t enc_sub = (single_phase_encoder_t)enc;
    rvm_hal_gpio_pin_close((rvm_dev_t *)(enc_sub->pin));

    free(enc);

    return 0;
}

single_phase_encoder_t single_phase_encoder_create(signed long pin, unsigned short pulse_revol, unsigned short sample_time)
{
    rvm_gpio_pin_drv_register(pin);

    // Malloc memory and initialize pulse_count and pin
    single_phase_encoder_t new_encoder = (single_phase_encoder_t)encoder_create(sizeof(struct single_phase_encoder), sample_time);
    if(new_encoder == NULL)
    {
        return NULL;
    }

    char filename[16];
    sprintf(filename, "gpio_pin%ld", pin);
    gpio_pin = rvm_hal_gpio_pin_open(filename);

    new_encoder->pin = gpio_pin;
    new_encoder->enc.pulse_revol = pulse_revol;
    new_encoder->enc.enable = single_phase_encoder_enable;
    new_encoder->enc.disable = single_phase_encoder_disable;
    new_encoder->enc.destroy = single_phase_encoder_destroy;

    return new_encoder;
}
